// *******************************************************************************
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
// *******************************************************************************
using System;
using System.Collections;
using System.Windows.Forms;
using nDeveloper.VSS.IVSSFunctionLibrary;
using System.Xml.Serialization;
using System.IO;
using nDeveloper.VSS.DifferenceEngine;

namespace nDeveloper.VSS
{
	/// <summary>
	/// Summary description for VSSConnection.
	/// </summary>
	[Serializable]
	public class VSSConnection
	{
		public clIVSSLibrary IVSS = new clIVSSLibrary();
		private frmLogin frmLogin;
 
		public enum DBObjectTypes
		{
			Template,
			DomainFiles,
			None,
		}
		
		private string pathString =  @"{0}\{1}\Databases\{2}\{3}";
		private string _parentProject;
		private string _server;
		private string _database;
		public string _comment;
		private bool _isLoggedin = false;
		private string _WorkingDir;
		public string VSSDatabasePath;
		public string UserName;
		public string Password;
		public bool RememberPassword;
		public bool IsCanceled = false;
		public bool IsPersisted = false;

		public string ParentProject
		{
			get{return _parentProject;}
			set
			{
				_parentProject=value;
				IVSS.SetCurrentProject(_parentProject);
			}
		}

		public string Server
		{
			get{return _server;}
			set{_server = value;}
		}
		public string Database
		{
			get{return _database;}
			set{_database = value;}
		}

		public bool IsLoggedIn
		{
			get
			{
				if (frmLogin != null)
				{
					this.IVSS=frmLogin.IVSS;
					string retval = this.IVSS.IsUserValid(UserName, ref _isLoggedin);
					if (retval.Length == 0)
					{
						string currProj = this.IVSS.GetCurrentProject();
						_isLoggedin = _isLoggedin && currProj.IndexOf( ParentProject.Replace( @"\", "/" ) ) >= 0;
					}
				}
				return  _isLoggedin;
			}
		}

		/// <summary>
		/// Added this working dir to set the working dir for the current vssConnection
		/// </summary>
		public string WorkingDir
		{
			get
			{
				return _WorkingDir;
			}
			set
			{
				_WorkingDir = value;
				_WorkingDir = _WorkingDir.TrimEnd('\\');
				IVSS.SetWorkingFolder(_parentProject, _WorkingDir);
			}
		}

		public string GetCheckOutPath(DBObjectTypes type, string itemPath)
		{
			string _checkoutpath = null;
			string retval = IVSS.GetCheckOutFolder(itemPath, UserName, ref _checkoutpath);
			if (retval != "" || _checkoutpath== null || _checkoutpath.Length == 0)
			{
				_checkoutpath = _WorkingDir + "\\" + type.ToString();
			}
			return _checkoutpath;
		}

		public void Login()
		{
			if(!this.IsLoggedIn)
			{
				frmLogin = new frmLogin(this);
				if(frmLogin.IsLoggedIn || frmLogin.ShowDialog()==DialogResult.OK)
				{
					this.IVSS = frmLogin.IVSS;
					if (Server != null)
					{
						if (Database == null)
						{
							CreateWorkSpace(Server, "");
						}
						else
						{
							CreateWorkSpace(Server, Database,"");
						}
						_isLoggedin = true;
					}
				}
			}
		}
		
		public int GetStatus(string filePath)
		{
			int status=0;
			string msg = IVSS.GetCheckOutState(filePath, ref status);
			if (msg.Length > 0)
			{
				status = -1;
			}
			return status;
		}

		public string GetHistory(string filePath, string localFilePath)
		{
			string fileName = GetVSSFileName(filePath);
			string[,] hitoryitems;
			
			string ret = IVSS.GetHistory(out hitoryitems, filePath, 1073745920);

			if(ret.Length>0)
			{
				MessageBox.Show(ret,"Visual SourceSafe");
				return"";
			}
			VSSHitoryItemCollection vssHitoryItemCollection = new VSSHitoryItemCollection();

			for(int count = hitoryitems.GetUpperBound(0); count >= 0; count--)
			{
				VSSHitoryItem item = new VSSHitoryItem();
				item.Text = hitoryitems[count, (int)VSSEnums.HistoryItems.VersionNumber];
				item.Username = hitoryitems[count, (int)VSSEnums.HistoryItems.UserName];
				item.Date = hitoryitems[count, (int)VSSEnums.HistoryItems.Date];
				item.Action = hitoryitems[count, (int)VSSEnums.HistoryItems.Action];
				vssHitoryItemCollection.Add(item);
			}
			frmShowHistory frm = new frmShowHistory(vssHitoryItemCollection);
			
			frm.Text=fileName + " history";
			frm.HistoryLabel.Text=hitoryitems.GetUpperBound(0).ToString() + " history items";
			
			///
			/// Difference between two selected items from the history list
			/// 
			DialogResult dr = frm.ShowDialog();

			if(dr == DialogResult.OK)
			{
				// ShowDiff
				IVSSFlags.VSSFlags flags = new IVSSFlags.VSSFlags();
				int version1 = Convert.ToInt16( frm.HistoryList.SelectedItems[0].Text);
				int version2 = Convert.ToInt16( frm.HistoryList.SelectedItems[1].Text);
				int flag = (int)flags.FlagReplaceLocalReplace();
				IVSS.GetVersionByVersionNumber(filePath, version1, _WorkingDir + "\\version1", flag);
				IVSS.GetVersionByVersionNumber(filePath, version2, _WorkingDir + "\\version2", flag);
			
				TextDiff( _WorkingDir + "\\version1", _WorkingDir + "\\version2");

				return _WorkingDir + "\\version1|"+ _WorkingDir + "\\version1";
			}

			///
			///Difference with currently local checked out object
			///

			if(dr==DialogResult.Yes)
			{
				// ShowDiff
//				if (this.GetStatus(filePath) != 2)
//				{
//					MessageBox.Show("The file you selected is currently not checked out!","Visual Source Safe");
//					return "";
//				}
				IVSSFlags.VSSFlags flags = new IVSSFlags.VSSFlags();
				int version1 = Convert.ToInt16( frm.HistoryList.SelectedItems[0].Text);
				int flag = (int)flags.FlagReplaceLocalReplace();
				IVSS.GetVersionByVersionNumber(filePath, version1, _WorkingDir + "\\version1", flag);
				
				TextDiff( _WorkingDir + "\\version1", localFilePath);
				
				return _WorkingDir + "\\version1|"+ _WorkingDir + "\\version1";
			}
			return "";
		}

		public static void TextDiff(string sFile, string dFile)
		{
			DiffList_TextFile file1 = null;
			DiffList_TextFile file2 = null;
			try
			{
				file1 = new DiffList_TextFile(sFile);
				file2 = new DiffList_TextFile(dFile);
			}
			catch (Exception exception1)
			{
				MessageBox.Show(exception1.Message, "File Error");
				return;
			}
			try
			{
				double num1 = 0;
				DiffEngine engine1 = new DiffEngine();
				num1 = engine1.ProcessDiff(file1, file2, DifferenceEngine.DiffEngineLevel.Medium);
				ArrayList list1 = engine1.DiffReport();
				frmShowDiff results1 = new frmShowDiff(file1, file2, list1, num1);
				results1.ShowDialog();
				results1.Dispose();
			}
			catch (Exception exception2)
			{
				string text1 = string.Format("{0}{1}{1}***STACK***{1}{2}", exception2.Message, Environment.NewLine, exception2.StackTrace);
				MessageBox.Show(text1, "Compare Error");
				return;
			}
		}

		private string GetVSSFileName(string filePath)
		{
			return filePath.Substring(filePath.LastIndexOf("\\")+1);
		}

		public void CreateWorkSpace(string serverName, string databaseName, string comment)
		{
			string ret="";
			
			ret=IVSS.CreateProject(ParentProject, serverName, "");

			ret=IVSS.CreateProject(ParentProject + "\\" + serverName, "Databases", "");
			ret=IVSS.CreateProject(ParentProject + "\\" + serverName + "\\Databases", databaseName, comment);

			ret=IVSS.CreateProject(ParentProject + "\\" + serverName + "\\Databases\\" + databaseName, "Tables", comment);
			ret=IVSS.CreateProject(ParentProject + "\\" + serverName + "\\Databases\\" + databaseName, "Views", comment);
			ret=IVSS.CreateProject(ParentProject + "\\" + serverName + "\\Databases\\" + databaseName, "Stored procedures", comment);
			ret=IVSS.CreateProject(ParentProject + "\\" + serverName + "\\Databases\\" + databaseName, "Functions", comment);
			ret=IVSS.CreateProject(ParentProject + "\\" + serverName + "\\Databases\\" + databaseName, "Triggers", comment);
			ret=IVSS.CreateProject(ParentProject + "\\" + serverName + "\\Databases\\" + databaseName, "Defaults", comment);
			ret=IVSS.CreateProject(ParentProject + "\\" + serverName + "\\Databases\\" + databaseName, "Rules", comment);
			ret=IVSS.CreateProject(ParentProject + "\\" + serverName + "\\Databases\\" + databaseName, "UTDs", comment);

			ret=IVSS.CreateProject(ParentProject + "\\" + serverName, "Jobs", comment);
		}

		public void CreateWorkSpace(string serverName, string comment)
		{
			string ret="";
			
			ret=IVSS.CreateProject(ParentProject, serverName, "");
			ret=IVSS.CreateProject(ParentProject + "\\" + serverName, "Jobs", comment);			
		}

		public void AddItem(DBObjectTypes type, string ItemToAddPath, string AddComment)
		{
			bool persist_comment = false;
			try
			{
				if (_comment == null && AddComment == null )
				{
					frmAddComment frm = new frmAddComment();
					if ( this.IsPersisted )
					{
						frm.chkPersist.Visible = true;
					}
					if(frm.ShowDialog() == DialogResult.Cancel)
					{
						_comment = null;
						return;
					}
					_comment = frm.txtComment.Text;
					persist_comment = frm.chkPersist.Checked;
				}
				else if (AddComment != null)
				{
					_comment = AddComment;
				}
				IVSS.SetCurrentProject(GetVSSPath(type));
				string ret =IVSS.AddItem(GetVSSPath(type), ItemToAddPath, _comment, 0);
				if (!persist_comment)
				{
					_comment = null;
				}
			}
			catch(Exception ex)
			{
				MessageBox.Show(ex.Message, "Visual SourceSafe");
			}
		}

		public void AddItem( string VSSPath, string ItemToAddPath, string AddComment )
		{
			try
			{
				if (_comment == null && (AddComment == null || AddComment == ""))
				{
					frmAddComment frm = new frmAddComment();
					frm.chkPersist.Visible = true;
					if(frm.ShowDialog()==DialogResult.Cancel)
					{
						_comment = null;
						return;
					}
					_comment = frm.txtComment.Text;
				}
				else if (AddComment != null && AddComment != "")
				{
					_comment = AddComment;
				}
				IVSS.SetCurrentProject(VSSPath);
				string ret = IVSS.AddItem(VSSPath, ItemToAddPath, _comment, 0);
//				if(ret.Length>0)
//					MessageBox.Show(ret, "Visual SourceSafe");
				FileInfo fi = new FileInfo(ItemToAddPath);
				ret = IVSS.SetWorkingFolder(VSSPath, fi.DirectoryName);
				if(ret.Length>0)
					MessageBox.Show(ret, "Visual SourceSafe");
			}
			catch(Exception ex)
			{
				MessageBox.Show(ex.Message, "Visual SourceSafe");
			}
		}

		public void CheckOutItem( DBObjectTypes type, string ItemToCheckOut, string CheckOutPath, string Comment )
		{
			try
			{
				ItemToCheckOut= GetVSSPath(type) + "\\" + ItemToCheckOut;
				string ret =IVSS.CheckOutItem( ItemToCheckOut, CheckOutPath, ref Comment, 0 );
				if(ret.Length>0)
					MessageBox.Show(ret, "Visual SourceSafe");
			}
			catch(Exception ex)
			{
				MessageBox.Show(ex.Message, "Visual SourceSafe");
			}
		}

		public void CheckOutItem( string VSSPath, string CheckOutPath, string Comment )
		{
			try
			{
				string ret =IVSS.CheckOutItem(VSSPath, CheckOutPath, ref Comment, 0);
				if(ret.Length > 0)
					MessageBox.Show(ret, "Visual SourceSafe");
			}
			catch(Exception ex)
			{
				MessageBox.Show(ex.Message, "Visual SourceSafe");
			}
		}

		public void CheckOutItem( DBObjectTypes type, string VSSPath, string Comment )
		{
			try
			{
				string _checkOutPath = GetCheckOutPath(type, VSSPath);
				string ret =IVSS.CheckOutItem(VSSPath, _checkOutPath, ref Comment, 0);
				if(ret.Length>0)
					MessageBox.Show(ret, "Visual SourceSafe");
			}
			catch(Exception ex)
			{
				MessageBox.Show(ex.Message, "Visual SourceSafe");
			}
		}

		public void UndoCheckOut( string VSSPath, string CheckOutPath, string Comment )
		{
			try
			{
				string ret = IVSS.UnCheckOutItem(VSSPath, CheckOutPath,0);
				if(ret.Length>0)
					MessageBox.Show(ret, "Visual SourceSafe");
			}
			catch(Exception ex)
			{
				MessageBox.Show(ex.Message, "Visual SourceSafe");
			}
		}

		public void UndoCheckOut( DBObjectTypes type, string VSSPath, string Comment )
		{
			try
			{
				string _checkOutPath = GetCheckOutPath(type, VSSPath);
				string ret = IVSS.UnCheckOutItem(VSSPath, _checkOutPath,0);
				if(ret.Length>0)
					MessageBox.Show(ret, "Visual SourceSafe");
			}
			catch(Exception ex)
			{
				MessageBox.Show(ex.Message, "Visual SourceSafe");
			}
		}

		public void CheckInItem( DBObjectTypes type, string ItemToCheckIn, string CheckInPath, string Comment )
		{
			try
			{
				ItemToCheckIn = GetVSSPath(type) + "\\" + ItemToCheckIn;
				string ret =IVSS.CheckInItem(ItemToCheckIn, CheckInPath, ref Comment, (int)(SourceSafeTypeLib.VSSFlags.VSSFLAG_KEEPNO | SourceSafeTypeLib.VSSFlags.VSSFLAG_UPDASK));
				if(ret.Length>0)
					MessageBox.Show(ret, "Visual SourceSafe");
			}
			catch(Exception ex)
			{
				MessageBox.Show(ex.Message, "Visual SourceSafe");
			}
		}
		public void CheckInItem( string VSSPath,  string CheckInPath, string Comment)
		{
			try
			{
				frmAddComment frm = new frmAddComment();
				if(frm.ShowDialog()==DialogResult.Cancel)
					return;
				
				string comment=frm.txtComment.Text;
				string ret =IVSS.CheckInItem(VSSPath, CheckInPath, ref comment, 0);
				if(ret.Length>0)
					MessageBox.Show(ret, "Visual SourceSafe");
			}
			catch(Exception ex)
			{
				MessageBox.Show(ex.Message, "Visual SourceSafe");
			}
		}
		
		public string GetVSSPath(DBObjectTypes type)
		{
			switch(type)
			{
				case DBObjectTypes.Template:
					return String.Format(pathString, ParentProject, _server, _database, "Template");

				case DBObjectTypes.DomainFiles:
					return String.Format(pathString, ParentProject, _server, _database, "Domain files");

				default:
					return "";

			}
		}
	}
}
